using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Editor.UiViewManagerNameGenerator;
using Microsoft.Extensions.Primitives;
using UnityEditor;
using UnityEditor.Experimental;
using UnityEngine;
using UnityEngine.UIElements;
using Object = UnityEngine.Object;

public class UINamesGenerator : EditorWindow
{

    private static TextField pathInput;
    private static Button selectPrefabPath;
    private static TextField scriptPathInput;
    private static Button selectScriptPath;
    private static TextField scriptFileName;
    private static Button generator;
    private static Label msgInfo;
    private static VisualElement root;
    private static TextField scriptNamingSpace;

    private static GeneratorConfig _config;
    private static string dataPath;
    
    [MenuItem("Tools/UINamesGenerator")]
    public static void ShowWindow()
    {
        _config = AssetDatabase.LoadAssetAtPath<GeneratorConfig>(
            "Assets/Editor/UiViewManagerNameGenerator/config.asset");
        UINamesGenerator uiNamesGenerator = GetWindow<UINamesGenerator>("UI管理器名字生成",true);

        uiNamesGenerator.maxSize = new Vector2(510, 200);
        uiNamesGenerator.Show();
        dataPath = Application.dataPath;
        // Debug.Log("dataPath:"+dataPath);

    }

    private static void bindableElement()
    {
        // pathinp
        pathInput = root.Q<TextField>(className:"pathInput");
        pathInput.RegisterCallback<BlurEvent>((e) => prefabInputBlure());
        
        selectPrefabPath = root.Q<Button>(className:"selectPrefabPath");
        selectPrefabPath.RegisterCallback<ClickEvent>((e)=>selectPrefabPathClick());
        
        scriptPathInput = root.Q<TextField>(className:"scriptPathInput");
        
        scriptNamingSpace = root.Q<TextField>(className:"scriptNamingSpace");
        scriptNamingSpace.RegisterCallback<BlurEvent>((e) => scriptNamingSpaceInputBlure());
        scriptFileName = root.Q<TextField>(className:"scriptFileName");
        scriptFileName.RegisterCallback<BlurEvent>((e) => scriptFileNameInputBlure());
        
        selectScriptPath = root.Q<Button>(className:"selectScriptPath");
        selectScriptPath.RegisterCallback<ClickEvent>((e)=>selectScriptPathClick());
        
        generator = root.Q<Button>(className:"generator");
        generator.RegisterCallback<ClickEvent>((e)=>generatorScript());

        msgInfo = root.Q<Label>(className:"msgInfo");
        setDataFromConfig();

    }

    private static void scriptNamingSpaceInputBlure()
    {
        _config.nameSpace = scriptNamingSpace.value;
    }

    private static void scriptFileNameInputBlure()
    {
        if (scriptFileName.value.Equals(""))
        {
            scriptFileName.value = "SceneViewManagerNames";
            _config.scriptFileName = "SceneViewManagerNames";
            return;
        }
        _config.scriptFileName = scriptFileName.value;
    }

    private static void prefabInputBlure()
    {
        Debug.Log("预制体路径输入框失去焦点！");
        string value = pathInput.value;
        if (value.Equals(""))
        {
            return;
        }

        if (!value.StartsWith(dataPath))
        {
            msgError("预制件的路径必须在项目的Asstes目录下");
            return;
        }

        pathInput.value =  "Assets" + value.Replace(dataPath, "");
        _config.prefabPath = pathInput.value;
    }

    private static void setDataFromConfig()
    {
        pathInput.value = _config.prefabPath;
        scriptPathInput.value = _config.scriptPath;
        scriptFileName.value = _config.scriptFileName;
        scriptNamingSpace.value = _config.nameSpace;
        msgInfo.text = "";
    }

    private static void generatorScript()
    {
        if (!canGenerator())
        {
            return;
        }
        GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(_config.prefabPath);
        if (prefab == null)
        {
            msgError("预制件加载失败！");
            return;
        }

        Object node = UnityEditor.PrefabUtility.InstantiatePrefab(prefab);

        if (node == null)
        {
            msgError("预制件实例化失败！");
            return;
        }
        
        GameObject nodeObj = node as GameObject;
        Transform sceneUI = nodeObj.transform.Find("SceneUI");
        int childCount = sceneUI.childCount;
        List<string> names = new List<string>();
        for (int i = 0; i < childCount; i++)
        {
            string s = sceneUI.GetChild(i).name;
            if (s.EndsWith("UI"))
            {
                s = s.Substring(0, s.Length - 2);
            }
            names.Add(s);
        }

        if (!Directory.Exists(_config.scriptPath))
        {
            Directory.CreateDirectory(_config.scriptPath);
        }

        StringBuilder sb = new StringBuilder();
        doneContent(sb,names);
        File.WriteAllText(_config.scriptPath + "/" + scriptFileName.value + ".cs", sb.ToString());
        DestroyImmediate(nodeObj);
        // Instantiate()
        msgSuccess("生成成功！");
    }

    private static void doneContent(StringBuilder sb, List<string> names)
    {
        if (_config.nameSpace.Length > 0)
        {
            sb.Append("namespace ").Append(_config.nameSpace).Append("\n");
            sb.Append("{");
            sb.Append("    public class ").Append(_config.scriptFileName).Append("\n");
            sb.Append("    {\n");
            foreach (string name in names)
            {
                sb.Append("        public const string ").Append(name).Append(" = ").Append("\"").Append(name).Append("\";\n");
            }

            sb.Append("    }\n");
            sb.Append("}");
        }
        else
        {
            sb.Append("public class ").Append(_config.scriptFileName).Append("\n");
            sb.Append("{\n");
            foreach (string name in names)
            {
                sb.Append("    public const string ").Append(name).Append(" = ").Append("\"").Append(name).Append("\"\n");
            }
            sb.Append("}\n");
        }

    }

    private static void msgError(string msg)
    {
        msgInfo.style.color = Color.red;
        msgInfo.text = msg;
    }
    private static void msgSuccess(string msg)
    {
        msgInfo.style.color = Color.green;
        msgInfo.text = msg;
    }

    private static bool canGenerator()
    {
        if (_config.prefabPath == null || _config.prefabPath == "")
        {
            msgError("预制件路径为空。生成失败！");
            return false;
        }
        if (_config.scriptPath == null || _config.scriptPath == "")
        {
            msgError("脚本生成路径为空。生成失败！");
            return false;
        }
        

        return true;
    }

    private static void selectPrefabPathClick()
    {
        pathInput.value = EditorUtility.OpenFilePanel("选择UI根节点预制件", UnityEngine.Application.dataPath, "prefab");
        string value = pathInput.value;
        if (!value.StartsWith(dataPath))
        {
            msgError("预制件的路径必须在项目的Asstes目录下");
            return;
        }

        pathInput.value =  "Assets" + value.Replace(dataPath, "");
        _config.prefabPath = pathInput.value;
    }
    private static void selectScriptPathClick()
    {
        scriptPathInput.value = EditorUtility.OpenFolderPanel("选择脚本生成路径", UnityEngine.Application.dataPath,"");
        _config.scriptPath = scriptPathInput.value;
    }

    private void CreateGUI()
    {
        // rootVisualElement.Add();
        VisualTreeAsset asset = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/Editor/UiViewManagerNameGenerator/window/window.uxml");
        asset.CloneTree(rootVisualElement);
        root = rootVisualElement;
        bindableElement();
    }
}
